/*
 * sms.c : uRobot Sensor Monitering Service.
 * Originally developped for the uRobot project.
 * Parts of the code are originated from GMediaServer from Oskar Liljeblad.
 * Copyright (C) 2011-2012 Seong-Woo Kim <libero@deu.ac.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <stdlib.h>
#include <upnp/upnp.h>
#include <upnp/upnptools.h>

#include "urobot.h"
#include "services.h"
#include "mime.h"
#include "sms.h"
#include "target.h"

/* Represent the SMS SetFrontLightSensor action. */
#define SERVICE_SMS_ACTION_SET_FRONT_LIGHT "SetFrontLight"

/* Represent the SMS SetFogLight action. */
#define SERVICE_SMS_ACTION_SET_FOG_LIGHT "SetFogLight"

/* Represent the SMS SetBreakLightSensor action. */
#define SERVICE_SMS_ACTION_SET_BREAK_LIGHT "SetBreakLight"

/* Represent the SMS SetWinkerLight action. */
#define SERVICE_SMS_ACTION_SET_WINKER_LIGHT "SetWinkerLight"

/* Represent the SMS GetFrontDistance action. */
#define SERVICE_SMS_ACTION_GET_FRONT_DISTANCE "GetFrontDistance"

/* Represent the SMS GetBackDistance action. */
#define SERVICE_SMS_ACTION_GET_BACK_DISTANCE "GetBackDistance"

/* Represent the SMS GetLeftDistance action. */
#define SERVICE_SMS_ACTION_GET_LEFT_DISTANCE "GetLeftDistance"

/* Represent the SMS GetRightDistance action. */
#define SERVICE_SMS_ACTION_GET_RIGHT_DISTANCE "GetRightDistance"

/* Represent the SMS GetAccelerator action. */
#define SERVICE_SMS_ACTION_GET_ACCELERATOR "GetAccelerator"

/* Represent the SMS GetCurrentSensorInfo action. */
#define SERVICE_SMS_ACTION_GET_SENSOR_INFO "GetSensorInfo"

/* Represent the SMS Command argument. */
#define SERVICE_SMS_ARG_COMMAND "Command"

/* Represent the SMS Status argument. */
#define SERVICE_SMS_ARG_STATUS "Status"

/* Represent the SMS Status value. */
#define SERVICE_SMS_STATUS_OK "OK"

/* Represent the SMS SensorID argument. */
#define SERVICE_SMS_ARG_SENSOR_ID "SensorID"

/* Represent the SMS default Sensor ID value. */
#define SERVICE_SMS_DEFAULT_SENSOR_ID "0"

/* Represent the SMS unknown connection ID value. */
#define SERVICE_SMS_UNKNOW_ID "-1"

/* Represent the SMS Sensor value. */
#define SERVICE_SMS_ARG_SENSOR_VALUE "SensorValue"

/* Represent the SMS Default Sensor value. */
#define SERVICE_SMS_DEFAULT_VALUE "0"

static bool
sms_set_front_light (struct action_event_t *event)
{
  int command;
  char value[20];

  if (!event)
    return false;

  /* Retrieve SetFrontLight arguments */
  command = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  printf("command=%d\n", command);
  // make action to set front light of the car
  set_sensor_data(LIGHT_SENSOR, FRONT_LIGHT_SENSOR, command);

  sprintf(value, "%d", command);
  if (upnp_set_variable (SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_FRONT_LIGHT, value)) {
    printf("value=%s\n", value);
    upnp_add_response (event, SERVICE_SMS_ARG_STATUS, SERVICE_SMS_STATUS_OK);
  }

  return event->status;
}

static bool
sms_set_fog_light (struct action_event_t *event)
{
  int command;
  char value[20];

  if (!event)
    return false;

  /* Retrieve SetFogLight arguments */
  command = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  // make action to set fog light of the car
  set_sensor_data(LIGHT_SENSOR, FOG_LIGHT_SENSOR, command);

  sprintf(value, "%d", command);
  if (upnp_set_variable (SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_FOG_LIGHT, value)) {
    upnp_add_response (event, SERVICE_SMS_ARG_STATUS, SERVICE_SMS_STATUS_OK);
  }

  return event->status;
}

static bool
sms_set_break_light (struct action_event_t *event)
{
  int command;
  char value[20];

  if (!event)
    return false;

  /* Retrieve SetBreakLight arguments */
  command = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  // make action to set break light of the car
  set_sensor_data(LIGHT_SENSOR, BREAK_LIGHT_SENSOR, command);

  sprintf(value, "%d", command);
  if (upnp_set_variable (SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_BREAK_LIGHT, value)) {
    upnp_add_response (event, SERVICE_SMS_ARG_STATUS, SERVICE_SMS_STATUS_OK);
  }

  return event->status;
}

static bool
sms_set_winker_light (struct action_event_t *event)
{
  int command;
  char value[20];

  if (!event)
    return false;

  /* Retrieve SetWinkerLight arguments */
  command = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  // make action to set winker light of the car
  set_sensor_data(LIGHT_SENSOR, WINKER_LIGHT_SENSOR, command);

  sprintf(value, "%d", command);
  if (upnp_set_variable (SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_WINKER_LIGHT, value)) {
    upnp_add_response (event, SERVICE_SMS_ARG_STATUS, SERVICE_SMS_STATUS_OK);
  }

  return event->status;
}

static bool
sms_get_front_distance (struct action_event_t *event)
{
  int command;
  char value[20];

  if (!event)
    return false;

  /* Retrieve Stop arguments */
  command = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  // make action to get front distance car
  upnp_get_variable(SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_FRONT_DISTANCE, value);

  upnp_add_response (event, SERVICE_SMS_ARG_SENSOR_VALUE, value);

  return event->status;
}

static bool
sms_get_back_distance (struct action_event_t *event)
{
  int command;
  char value[20];

  if (!event)
    return false;

  /* Retrieve Stop arguments */
  command = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  // make action to get back distance car
  upnp_get_variable(SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_BACK_DISTANCE, value);

  upnp_add_response (event, SERVICE_SMS_ARG_SENSOR_VALUE, value);

  return event->status;
}

static bool
sms_get_left_distance (struct action_event_t *event)
{
  int command;
  char value[20];

  if (!event)
    return false;

  /* Retrieve Stop arguments */
  command = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  // make action to get left distance car
  upnp_get_variable(SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_LEFT_DISTANCE, value);

  upnp_add_response (event, SERVICE_SMS_ARG_SENSOR_VALUE, value);

  return event->status;
}

static bool
sms_get_right_distance (struct action_event_t *event)
{
  int command;
  char value[20];

  if (!event)
    return false;

  /* Retrieve Stop arguments */
  command = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  // make action to get right distnace car
  upnp_get_variable(SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_RIGHT_DISTANCE, value);

  upnp_add_response (event, SERVICE_SMS_ARG_SENSOR_VALUE, value);

  return event->status;
}

static bool
sms_get_accelerator (struct action_event_t *event)
{
  int index;
  char value[20];

  if (!event)
    return false;

  /* Retrieve index arguments */
  index = upnp_get_ui4 (event->request, SERVICE_SMS_ARG_COMMAND);

  // make action to get accelerator sensor
  upnp_get_variable(SMS_SERVICE_INDEX, SERVICE_SMS_INDEX_ACCELERATOR_X-index, value);

  upnp_add_response (event, SERVICE_SMS_ARG_SENSOR_VALUE, value);

  return event->status;
}

static bool
sms_get_current_sensor_info (struct action_event_t *event)
{
  if (!event)
    return false;

  upnp_add_response (event, SERVICE_SMS_ARG_SENSOR_ID,
                     SERVICE_SMS_DEFAULT_SENSOR_ID);

  upnp_add_response (event, SERVICE_SMS_ARG_STATUS, SERVICE_SMS_STATUS_OK);

  return event->status;
}

/* List of UPnP ConnectionManager Service actions */
struct service_action_t sms_service_actions[] = {
  { SERVICE_SMS_ACTION_SET_FRONT_LIGHT, sms_set_front_light },
  { SERVICE_SMS_ACTION_SET_FOG_LIGHT, sms_set_fog_light },
  { SERVICE_SMS_ACTION_SET_BREAK_LIGHT, sms_set_break_light },
  { SERVICE_SMS_ACTION_SET_WINKER_LIGHT, sms_set_winker_light },
  { SERVICE_SMS_ACTION_GET_FRONT_DISTANCE, sms_get_front_distance },
  { SERVICE_SMS_ACTION_GET_BACK_DISTANCE, sms_get_back_distance },
  { SERVICE_SMS_ACTION_GET_LEFT_DISTANCE, sms_get_left_distance },
  { SERVICE_SMS_ACTION_GET_RIGHT_DISTANCE, sms_get_right_distance },
  { SERVICE_SMS_ACTION_GET_ACCELERATOR, sms_get_accelerator },
  { SERVICE_SMS_ACTION_GET_SENSOR_INFO, sms_get_current_sensor_info },
  { NULL, NULL }
};

const char *sms_variablenames[] = {
  "FrontLight",
  "FogLight",
  "BreakLight",
  "WinkerLight",
  "FrontDistance",
  "BackDistance",
  "LeftDistance",
  "RightDistance",
  "AcceleratorX",
  "AcceleratorY",
  "AcceleratorZ",
};

char *sms_variables[SMS_SERVICE_VARIABLE_COUNT];

char *sms_defaultvalues[] = {
  "0",
  "0",
  "0",
  "0",
  "100.0",
  "100.0",
  "100.0",
  "100.0",
  "0",
  "0",
  "0",
};

